<template>
  <!-- 顶部导航栏 -->
  <PageHeader />

  <div class="page">
    <div class="form-container">
      <h2 class="form-title">发布技术问题</h2>
      <p class="form-desc">请尽可能详细描述你的问题，以便专家快速响应。</p>

      <!-- 标题 -->
      <div class="form-group">
        <label class="form-label">标题 *</label>
        <input
            v-model="formData.title"
            type="text"
            placeholder="请输入问题标题"
            maxlength="100"
            class="custom-input"
            :class="{ 'error': titleError }"
            @blur="validateTitle"
        />
        <div class="input-tip">
          <span>{{ formData.title.length }}/100</span>
          <span v-if="titleError" class="error-text">{{ titleError }}</span>
        </div>
      </div>

      <!-- 类型 -->
      <div class="form-group">
        <label class="form-label">类型 *</label>
        <select
            v-model="formData.type"
            class="custom-select"
            :class="{ 'error': typeError }"
            @blur="validateType"
        >
          <option value="" disabled>请选择问题类型</option>
          <option v-for="item in typeOptions" :key="item.id" :value="item.id">
            {{ item.name }}
          </option>
        </select>
        <div v-if="typeError" class="error-text">{{ typeError }}</div>
      </div>

      <!-- 描述 -->
      <div class="form-group">
        <label class="form-label">问题描述 *</label>
        <MdEditor v-model="formData.description" :toolbars="customToolbars" @on-upload-img="handleUploadImage" />
        <div v-if="descError" class="error-text">{{ descError }}</div>
      </div>

      <!-- 预期结果 -->
      <div class="form-group">
        <label class="form-label">预期结果 *</label>
        <MdEditor v-model="formData.expected" :toolbars="customToolbars" @on-upload-img="handleUploadImage" />
        <div v-if="expectedError" class="error-text">{{ expectedError }}</div>
      </div>

      <!-- 附件上传 -->
      <div class="form-group">
        <label class="form-label">附件上传</label>
        <el-upload
            v-model:file-list="pendingFiles"
            :auto-upload="false"
            :on-change="handleFileChange"
            :on-remove="handleRemove"
            :limit="10"
            accept="
              .txt,.log,.out,
              .java,.py,.c,.cpp,.js,
              .html,.htm,.css,.scss,.json,.xml,
              .yml,.yaml,.properties,.sql,
              .md,.markdown
            "
            multiple
            class="custom-upload"
        >
          <button type="button" class="btn btn-outline">
            <svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" viewBox="0 0 24 24" width="18" height="18">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M9 19l6-6m-6 6l6 6" />
            </svg>
            选择文件
          </button>
          <template #tip>
            <div class="upload-tip">
              主要为需求文档、设计文档、示例代码、日志、报错相关信息等，支持常见文本格式，单个不超过 1MB，最多选择10个。
            </div>
          </template>
        </el-upload>
      </div>

      <!-- 指定专家 -->
      <div class="form-group" style="max-height: 290px; height: fit-content">
        <label class="form-label">指定专家 *</label>
        <div class="expert-search-wrapper">
          <input
              v-model="searchKeyword"
              type="text"
              placeholder="请输入用户名搜索专家"
              class="custom-input search-input"
              @input="debouncedSearch"
          />
          <ul v-if="showExpertList" class="expert-suggestion-list">
            <li
                v-for="expert in expertList"
                :key="expert.id"
                @click="toggleExpert(expert)"
                class="suggestion-item"
                :class="{ selected: formData.experts.includes(expert.id) }"
            >
              {{ expert.name }}
            </li>
            <li v-if="expertList.length === 0" class="suggestion-item empty">暂无匹配专家</li>
          </ul>
        </div>
        <div class="selected-experts">
          <span
              v-for="id in formData.experts"
              :key="id"
              class="tag tag-primary"
          >
            {{ getExpertNameById(id) }}
            <strong @click.stop="removeExpert(id)">×</strong>
          </span>
        </div>
        <div class="input-tip">
          最多可指定 3 名专家，点击标签可移除
        </div>
        <div v-if="expertsError" class="error-text">{{ expertsError }}</div>
      </div>

      <!-- 提交按钮 -->
      <div class="form-actions">
        <button type="button" class="btn btn-outline" @click="cancel">取消</button>
        <button type="button" class="btn btn-primary" @click="submitForm" :disabled="submitting">
          <span v-if="!submitting">提交审核</span>
          <span v-else>提交中...</span>
        </button>
      </div>
    </div>
  </div>
</template>

<script setup>
import {ref, reactive, onMounted, computed} from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import request from '@/utils/request'
import PageHeader from "@/components/PageHeader.vue"
import router from "@/router"
import { onBeforeRouteLeave } from "vue-router"
import { MdEditor } from 'md-editor-v3';
import 'md-editor-v3/lib/style.css';

// 定义你想要保留的工具栏按钮
const customToolbars = [
  'bold',      // 加粗
  'italic',    // 斜体
  '|',         // 分隔线
  'ul',        // 无序列表
  'ol',        // 有序列表
  '|',
  'code',      // 行内代码
  'code-block', // 代码块
  '|',
  'link',      // 链接
  'image',     // 图片（可去掉）
  '|',
  'revoke',    // 撤销
  'next'       // 重做
];

const handleUploadImage = async (files, callback) => {
  const formData = new FormData()
  formData.append('file', files[0])

  try {
    const res = await request.post('/api/attachment/upload-image', formData, {
      headers: { 'Content-Type': 'multipart/form-data' }
    })
    callback([res.data]) // 回调传入图片 URL 数组
  } catch (err) {
    ElMessage.error('图片上传失败')
    callback([]) // 失败也要调用，避免卡住
  }
}

// 所有类型选项
const typeOptions = ref([]);

async function loadTags() {
  const res = await request.get(`/api/tag/listAll`)
  typeOptions.value = res.data;
}

// ========== 表单数据 ==========
const formData = reactive({
  title: '',
  type: '',
  description: '',
  expected: '',
  experts: [] // 存储选中的 expert ID
})

// 所有错误信息
const errors = reactive({
  title: '',
  type: '',
  description: '',
  expected: '',
  experts: ''
})

// 输入防抖
let debounceTimer = null
const debouncedSearch = () => {
  clearTimeout(debounceTimer)
  debounceTimer = setTimeout(handleExpertSearch, 300)
}

// ========== 专家相关 ==========
const searchKeyword = ref('')
const showExpertList = ref(false)
const expertList = ref([])

// 加载推荐专家（默认）
const loadRecommendedExperts = async () => {
  try {
    const res = await request.get('/api/user/experts', { params: { limit: 10 } })
    expertList.value = res.data.map(user => ({
      id: user.id,
      name: `${user.username} - 技术专家`
    }))
    showExpertList.value = true
  } catch (err) {
    // console.error('加载专家失败:', err)
    // ElMessage.warning('无法加载专家列表')
  }
}

// 搜索专家
const handleExpertSearch = async () => {
  const keyword = searchKeyword.value.trim()
  if (!keyword || keyword.length < 1) {
    await loadRecommendedExperts()
    return
  }

  try {
    const res = await request.get('/api/user/experts', {
      params: { keyword, limit: 10 }
    })

    expertList.value = res.data.map(user => ({
      id: user.id,
      name: `${user.username} - 技术专家`
    }))
    showExpertList.value = true
  } catch (err) {
    // ElMessage.warning('搜索失败，请稍后再试')
  }
}

// 移除专家
const removeExpert = (id) => {
  const index = formData.experts.indexOf(id)
  if (index > -1) {
    formData.experts.splice(index, 1)
  }
}

// 1. 增加映射存储
const selectedExpertsMap = ref(new Map())

// 2. 更新 toggleExpert
const toggleExpert = (expert) => {
  const id = expert.id
  const index = formData.experts.indexOf(id)
  if (index > -1) {
    formData.experts.splice(index, 1)
  } else if (formData.experts.length < 3) {
    formData.experts.push(id)
    selectedExpertsMap.value.set(id, { id, name: expert.name }) // ✅ 缓存
  } else {
    ElMessage.warning('最多只能指定 3 名专家')
  }
}

// 3. 替换 getExpertNameById
const getExpertNameById = (id) => {
  return selectedExpertsMap.value.get(id)?.name || '未知专家'
}

// ========== 文件上传 ==========
const pendingFiles = ref([])

const handleFileChange = async (file, fileList) => {
  if (file.status !== 'ready') return

  try {
    const formData = new FormData()
    formData.append('file', file.raw)

    await request.post('/api/attachment/validate', formData, {
      headers: { 'Content-Type': 'multipart/form-data' }
    })

    ElMessage.success(`✅ 文件【${file.name}】校验通过`)
    removeSameNameFile(file, fileList)
  } catch (error) {
    // ElMessage.error(`❌ 文件【${file.name}】校验失败：${error.response?.data?.message || '格式或大小不合规'}`)
    setTimeout(() => {
      const index = fileList.findIndex(f => f.uid === file.uid)
      if (index > -1) fileList.splice(index, 1)
    }, 50)
  }
}

const removeSameNameFile = (file, fileList) => {
  const fileName = file.name
  const sameNameFiles = fileList.filter(f => f.name === fileName && f.uid !== file.uid)

  if (sameNameFiles.length > 0) {
    sameNameFiles.forEach(item => {
      const idx = pendingFiles.value.findIndex(p => p.uid === item.uid)
      if (idx > -1) pendingFiles.value.splice(idx, 1)
      // ElMessage.warning(`已移除同名文件【${fileName}】`)
    })
  }

  const exists = pendingFiles.value.some(f => f.uid === file.uid)
  if (!exists) {
    pendingFiles.value.push(file)
  }
}

const handleRemove = (file) => {
  const index = pendingFiles.value.findIndex(f => f.uid === file.uid)
  if (index > -1) pendingFiles.value.splice(index, 1)
}

// ========== 表单验证 ==========
const validateTitle = () => {
  errors.title = !formData.title.trim() ? '请输入标题' : ''
}
const validateType = () => {
  errors.type = !formData.type ? '请选择问题类型' : ''
}
const validateDescription = () => {
  errors.description = !formData.description.trim() ? '请输入问题描述' : ''
}
const validateExpected = () => {
  errors.expected = !formData.expected.trim() ? '请输入预期结果' : ''
}
const validateExperts = () => {
  if (formData.experts.length === 0) {
    errors.experts = '请至少指定一位专家'
  } else if (formData.experts.length > 3) {
    errors.experts = '最多指定 3 名专家'
  } else {
    errors.experts = ''
  }
}

// 计算属性绑定
const titleError = computed(() => errors.title)
const typeError = computed(() => errors.type)
const descError = computed(() => errors.description)
const expectedError = computed(() => errors.expected)
const expertsError = computed(() => errors.experts)

// ========== 提交 ==========
const submitting = ref(false)
let saved = false

const submitForm = () => {
  validateTitle()
  validateType()
  validateDescription()
  validateExpected()
  validateExperts()

  const hasError = Object.values(errors).some(err => !!err)
  if (hasError) {
    ElMessage.error('请检查表单填写内容')
    return
  }

  submitting.value = true

  request.post('/api/questions', {
    title: formData.title,
    type: formData.type,
    description: formData.description,
    expected: formData.expected,
    expertIds: formData.experts
  }).then(async (res) => {
    const questionId = res.data

    ElMessage.success('问题创建成功')

    // 上传附件
    if (pendingFiles.value.length > 0) {
      const uploadData = new FormData()
      pendingFiles.value.forEach(file => uploadData.append('files', file.raw))

      await request.post(`/api/attachment/save/${questionId}`, uploadData, {
        headers: { 'Content-Type': 'multipart/form-data' },
        timeout: 30000
      })

      // ElMessage.success(`✅ 成功上传 ${pendingFiles.value.length} 个附件`)
    }

    saved = true
    toPath('/my')
  }).catch(err => {
    // ElMessage.error('提交失败，请稍后重试')
    console.error(err)
  }).finally(() => {
    submitting.value = false
  })
}

function toPath(path) {
  router.push({ path })
}

// 离开前确认
onBeforeRouteLeave(async () => {
  if (saved) return true
  return await ElMessageBox.confirm('确认离开？填写的内容将不会被保存。', '提示', { type: 'warning' })
      .then(() => true)
      .catch(() => false)
})

function cancel() {
  router.push('/my')
}

// 初始化
onMounted(() => {
  loadRecommendedExperts()
  loadTags();
})
</script>

<style scoped>
.page {
  min-height: calc(100vh - 70px);
  max-height: calc(100vh - 70px);
  background-color: var(--bg);
  padding: 40px 20px;
  display: flex;
  justify-content: center;
  overflow-y: auto;
}

.page::-webkit-scrollbar {
  width: 0.5rem;
}

.page::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 0.5rem;
}

.page::-webkit-scrollbar-thumb {
  background: #3498db;
  border-radius: 0.5rem;
}

.page::-webkit-scrollbar-thumb:hover {
  background: #2980b9;
}

.form-container {
  width: 100%;
  max-width: 1020px;
  background: var(--white);
  border-radius: 12px;
  box-shadow: var(--shadow);
  padding: 32px;
  border: 1px solid var(--border);
  height: fit-content;
}

.form-title {
  font-size: 24px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 8px;
}

.form-desc {
  color: var(--text-light);
  font-size: 15px;
  margin-bottom: 32px;
}

/* 表单项 */
.form-group {
  margin-bottom: 24px;
}

.form-label {
  display: block;
  margin-bottom: 8px;
  font-size: 14px;
  color: var(--text);
  font-weight: 500;
}

/* 自定义输入框 */
.custom-input,
.custom-select,
.custom-textarea {
  width: 100%;
  padding: 12px 16px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 14px;
  color: var(--text);
  background-color: white;
  transition: all 0.2s ease;
}

.custom-input:focus,
.custom-select:focus,
.custom-textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 2px rgba(30, 58, 138, 0.1);
}

.custom-input.error,
.custom-select.error,
.custom-textarea.error {
  border-color: #ff4d4f;
}

.custom-select {
  appearance: none;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor'%3e%3cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M19 9l-7 7-7-7'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 16px;
}

.custom-textarea {
  resize: none;
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

/* 错误提示 */
.error-text {
  font-size: 13px;
  color: #ff4d4f;
  margin-top: 6px;
}

.input-tip {
  display: flex;
  justify-content: space-between;
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 6px;
}

/* 上传组件 */
.custom-upload ::v-deep .el-upload {
  width: 100%;
}

.custom-upload ::v-deep .el-upload-list {
  margin-top: 12px;
}

.upload-tip {
  font-size: 13px;
  color: var(--text-muted);
  margin-top: 8px;
  line-height: 1.5;
}

/* 指定专家搜索区 */
.expert-search-wrapper {
  position: relative;
}

.search-input {
  padding-right: 32px;
}

.expert-suggestion-list {
  background: white;
  border: 1px solid var(--border);
  border-top: none;
  border-radius: 0 0 8px 8px;
  max-height: 218px;
  overflow-y: auto;
  z-index: 100;
  list-style: none;
  margin: 0;
  padding: 0;
  box-shadow: var(--shadow);
}

.suggestion-item {
  padding: 10px 16px;
  cursor: pointer;
  font-size: 14px;
  color: var(--text);
  border-bottom: 1px solid var(--border);
}

.suggestion-item:hover {
  background-color: #f8fafc;
}

.suggestion-item.selected {
  background-color: #eff6ff;
  color: var(--primary);
  font-weight: 500;
}

.suggestion-item.empty {
  color: var(--text-muted);
  font-style: italic;
}

/* 已选专家标签 */
.selected-experts {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}

.tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 8px;
  border-radius: 6px;
  font-size: 13px;
  background: var(--primary);
  color: white;
  cursor: default;
}

.tag strong {
  font-weight: bold;
  margin-left: 4px;
  cursor: pointer;
}

/* 操作按钮 */
.form-actions {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  margin-top: 32px;
}

.btn {
  padding: 10px 20px;
  border-radius: 8px;
  font-size: 15px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.btn-primary {
  background: var(--primary);
  color: white;
  border: none;
}

.btn-primary:hover:not(:disabled) {
  background: var(--primary-hover);
}

.btn-primary:disabled {
  background: #9fb5db;
  cursor: not-allowed;
}

.btn-outline {
  background: transparent;
  color: var(--primary);
  border: 1px solid var(--primary);
}

.btn-outline:hover {
  background: #ebf5ff;
}

/* 响应式 */
@media (max-width: 768px) {
  .form-container {
    padding: 24px;
  }

  .form-actions {
    flex-direction: column;
  }

  .btn {
    width: 100%;
    justify-content: center;
  }
}

textarea::placeholder {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

.expert-suggestion-list::-webkit-scrollbar {
  width: 0.5rem;
}

.expert-suggestion-list::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 0.5rem;
}

.expert-suggestion-list::-webkit-scrollbar-thumb {
  background: #3498db;
  border-radius: 0.5rem;
}

.expert-suggestion-list::-webkit-scrollbar-thumb:hover {
  background: #2980b9;
}

textarea::-webkit-scrollbar {
  width: 0.5rem;
}

textarea::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 0.5rem;
}

textarea::-webkit-scrollbar-thumb {
  background: #3498db;
  border-radius: 0.5rem;
}

textarea::-webkit-scrollbar-thumb:hover {
  background: #2980b9;
}
</style>
